//
// File  : FlightDatabase.cpp
// Team  : Dangling Pointers
// Class : CST 236 - Software Testing
//
// Implementation file for the FlightDatabase
// class methods.
//

#include <iomanip>
#include <iostream>
#include <exception>
#include "FlightDatabase.h"


// constructor
FlightDatabase::FlightDatabase() : m_database() 
{}

// 
// getFlight : const Flight&
//
// method takes a string representing key and will get a specified flight in the database
// if the specified flight is not in the database, it throws an exception
//
const Flight& FlightDatabase::getFlight(const std::string& key) const 
{
	FlightMapIterC iter = m_database.find(key);

	if (iter != m_database.end())
		return iter->second;

	throw std::exception();
}

//
// addFlight : void
//
// method takes a string representing the key and a reference to a flight object
// and will add a new flight to the flight database.
//
void FlightDatabase::addFlight(const std::string& key, const Flight& flight)
{
	m_database.insert(std::make_pair(key, flight));
}

//
// removeFlight : bool
//
// method takes a string representing the key and will erase the specified flight
// if there was an error erasing the flight, the function will return false to
// the client for error handling.
//
bool FlightDatabase::removeFlight(const std::string& key) 
{
	int numEr = m_database.erase(key);

	if (numEr == 1) 
		return true;
	else 
		return false;
}

//
// changeFlightDepartureTime : void
//
// method takes a string representing the key and a string representing the departure time
// it will look for the specified key in the database and will modify the departure time of the
// flight corresponding to that key if found. Otherwise, it throws an exception.
//
void FlightDatabase::changeFlightDepartureTime(const std::string& flightId, const std::string& departureTime) 
{
	FlightMapIter iter = m_database.find(flightId);

	if (iter != m_database.end())
		iter->second.setDepartureTime(departureTime);
	else
		throw std::exception();
}

//
// changeFlightArrivalTime : void
//
// method takes a string representing the key and a string representing the arrival time
// it will look for the specified key in the database and will modify the arrival time of the
// flight corresponding to that key if found. Otherwise, it throws an exception.
//
void FlightDatabase::changeFlightArrivalTime(const std::string& key, const std::string& val)
{
	FlightMapIter iter = m_database.find(key);

	if (iter != m_database.end())
		iter->second.setArrivalTime(val);
	else
		throw std::exception();
}

//
// changeFlightArrivalTime : void
//
// method takes a string representing the key and a string representing the flight status
// it will look for the specified key in the database and will modify the flight status of the
// flight corresponding to that key if found. Otherwise, it throws an exception.
//
void FlightDatabase::changeFlightStatus(const std::string& key, Flight::Status val)
{
	FlightMapIter iter = m_database.find(key);

	if (iter != m_database.end())
		iter->second.setFlightStatus(val);
	else
		throw std::exception();
}

//
// updateFirstClassSeating : void
//
// method takes a string represnting the key, an integer representing the seat number, and a string
// representing the passenger. It will look for the specfied key in the database and will update the
// first-class seat number with the passenger if the key is foun. Otherwise, it throws an exception.
//
void FlightDatabase::addFirstClassSeating(const std::string& key, const std::string& passenger)
{
	FlightMapIter iter = m_database.find(key);

	if (iter != m_database.end())
		iter->second.addFirstClassSeat(passenger);
	else
		throw std::exception();
}

//
// updateCoachClassSeating : void
//
// method takes a string represnting the key, an integer representing the seat number, and a string
// representing the passenger. It will look for the specfied key in the database and will update the
// coach seat number with the passenger if the key is foun. Otherwise, it throws an exception.
//
void FlightDatabase::addCoachClassSeating(const std::string& key, const std::string& passenger)
{
	FlightMapIter iter = m_database.find(key);

	if (iter != m_database.end())
		iter->second.addCoachClassSeat(passenger);
	else
		throw std::exception();
}


void FlightDatabase::removePassengerFromSeatingChart(const std::string& key, const std::string& passenger)
{
	FlightMapIter iter = m_database.find(key);

	if (iter != m_database.end())
	{
		if (iter->second.removeFirstClassSeat(passenger) == true)
			return;
		else
			iter->second.removeCoachClassSeat(passenger);
	}
	else 
		throw std::exception();

}

//
// printFlights : void
//
// Will print all the existing flights in the database in formatted output to the console.
// Otherwise, it will print "Zero Flights" to the console.
//
void FlightDatabase::printFlights() const 
{
	if (m_database.size() == 0)
	{
		std::cout << std::endl << "====== Zero Flights ======" 
			<< std::endl;
	}
	else 
	{
		std::cout << std::endl << "====== " 
			<< m_database.size() 
			<< " Flight(s) ======" 
			<< std::endl;

		std::cout << std::left
			<< std::setw(20) << "Flight#" 
			<< std::setw(20) << "Departure" 
			<< std::setw(20) << "Arrival" 
			<< "Status" 
			<< std::endl;

		for (int i = 0; i < 71; ++i)
			std::cout << "-";
		std::cout << std::endl;

		for (FlightMapIterC iter = m_database.begin(); iter != m_database.end(); ++iter)
			iter->second.print();
		std::cout << std::endl;
	}
}
